package model;

import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;

import org.apache.log4j.Logger;

import logic.InputActions;
import util.ImageUtil;

public abstract class Entity implements InputActions
{

	private String imageRef;
	protected double x;
	protected double y;
	protected Sprite sprite;
	protected double dx;
	protected double dy;
	protected double dr;
	protected double angle;
	private Rectangle me = new Rectangle();
	private Rectangle him = new Rectangle();
	private boolean isReversed = false;
	public boolean isFiring;

	// TODO: make these private, use getters
	public boolean _moveLeft = false;
	public boolean _moveRight = false;
	public boolean _moveUp = false;
	public boolean _moveDown = false;
	public boolean _rotateUp = false;
	public boolean _rotateDown = false;
	private int moveSpeed;
		
	Logger logger;

	public Entity(String ref, int x, int y)
	{
		this.imageRef = ref;
		this.sprite = SpriteStore.get().getSprite(imageRef);
		this.x = x;
		this.y = y;
		logger = Logger.getLogger(this.getClass().getName());
	}

	public void resizeSprite(double factor)
	{
		this.sprite.setImage(ImageUtil.getScaledImage(SpriteStore.get().getSprite(imageRef).getImage(), factor));
	}

	public void move(long modifier)
	{
		x += (modifier * dx) / 1000;
		y += (modifier * dy) / 1000;
	}
	
	public double getAngle(){
		return this.angle;
	}

	public int getMoveSpeed()
	{
		return moveSpeed;
	}

	public void setMoveSpeed(int moveSpeed)
	{
		this.moveSpeed = moveSpeed;
	}

	public void setHorizontalMovement(double dx)
	{
		this.dx = dx;
	}

	public void setVerticalMovement(double dy)
	{
		this.dy = dy;
	}

	public void setRotationSpeed(double dr)
	{
		this.dr = dr;
	}

	public double getHorizontalMovement()
	{
		return dx;
	}

	public double getVerticalMovement()
	{
		return dy;
	}

	public void draw(Graphics g)
	{
		if (isReversed())
		{
			BufferedImage bufferedImageSrc = this.sprite.getImage();
			BufferedImage flippedImage = ImageUtil.getImageFlippedHorizontal(bufferedImageSrc);
			g.drawImage(flippedImage, (int) x, (int) y, null);
		}
		else
		{
			sprite.draw(g, (int) x, (int) y);
		}
	}

	public void scaleImage(double factor)
	{
		this.sprite.setImage(ImageUtil.getScaledImage(this.sprite.getImage(), factor));
	}

	public int getX()
	{
		return (int) x;
	}

	public int getY()
	{
		return (int) y;
	}

	public int getWidth()
	{
		return this.sprite.getWidth();
	}

	public int getHeight()
	{
		return this.sprite.getHeight();
	}

	public boolean isReversed()
	{
		return isReversed;
	}

	public void setReversed(boolean isReversed)
	{
		this.isReversed = isReversed;
	}

	@Override
	public void left_pressed()
	{
		_moveLeft = true;
		_moveRight = false;
	}

	@Override
	public void right_pressed()
	{
		_moveRight = true;
		_moveLeft = false;
	}

	@Override
	public void up_pressed()
	{
		_moveUp = true;
		_moveDown = false;
	}

	@Override
	public void down_pressed()
	{
		_moveDown = true;
		_moveUp = false;
	}

	@Override
	public void left_released()
	{
		_moveLeft = false;
	}

	@Override
	public void right_released()
	{
		_moveRight = false;
	}

	@Override
	public void up_released()
	{
		_moveUp = false;
	}

	@Override
	public void down_released()
	{
		_moveDown = false;
	}

	@Override
	public void rotateUp_pressed()
	{
		_rotateUp = true;
		_rotateDown = false;
	}

	@Override
	public void rotateUp_released()
	{
		_rotateUp = false;		
	}
	
	@Override
	public void rotateDown_pressed()
	{
		_rotateDown = true;
		_rotateUp = false;
	}

	@Override
	public void rotateDown_released()
	{		
		_rotateDown = false;
	}

	@Override
	public void actionOne_pressed()
	{
		isFiring = true;
	}

	@Override
	public void actionOne_released()
	{
		isFiring = false;
	}

	@Override
	public void actionTwo_pressed()
	{
		if (isReversed)
		{
			isReversed = false;
		}
		else
		{
			isReversed = true;
		}

	}

	@Override
	public void actionTwo_released()
	{

	}

	public boolean collidesWith(Entity other)
	{
		me.setBounds((int) x, (int) y, sprite.getWidth(), sprite.getHeight());
		him.setBounds((int) other.x, (int) other.y, other.sprite.getWidth(), other.sprite.getHeight());

		return me.intersects(him);
	}

	public abstract void collidedWith(Entity other);

}